package de.koller.singularity;

import de.koller.aframe.util.ALoop;
import de.koller.aframe.util.node.NodeA;
import de.koller.aframe.util.thread.ICommand;
import de.koller.aframe.util.thread.ThreadRootHandle;
import de.koller.oceanFramework.tree.Child;
import de.koller.singularity.client.SClient;
import de.koller.singularity.engine.SEngine;
import java.util.Random;

public class SRoot extends NodeA {
	public static final Random RND = new Random();
	public static final String TITLE = "Singularity v0.1";
	
	private final ThreadRootHandle stepThread = new ThreadRootHandle( "step" );
	private long time = 0;
	
	@Child public final SEngine engine = new SEngine();
	@Child public final SClient client = new SClient();
	
	private final CalculationTime calcTimeCall = new CalculationTime();
	
	public static void startGame() {
		SRoot root = new SRoot();
		root.start();
	}

	private SRoot() {
	
	}
	
	public void start() {
		stepThread.start();
		
		this.call( new ICommand() {
			@Override public void handle( Object... params ) {
				initalize();
			}
		} );
	}
	
	@Override
	protected void init() {
		super.init();
		
		this.setIgnoreChildRender( true );
	}

	@Override
	protected void release() {
		super.release();
		
		stepThread.stop();
	}

	@Override
	protected void update( int elapsedTime ) {
		super.update( elapsedTime );
		
		time += 1;
	}

	@Override
	public void postChildUpdate( int elapsedTime ) {
		super.postChildUpdate( elapsedTime );
		
		client.display.updateDisplay();
	}
	
	
	
	public void stop() {
		stepThread.call( new ICommand() {
			@Override public void handle( Object... params ) {
				releasing();
			}
		} );
	}

	public void call( ICommand command ) {
		stepThread.call( calcTimeCall );
		
		stepThread.call( command );
		
		stepThread.call( new ICommand() {
			@Override public void handle( Object... params ) {
				updating( 1 );
			}
		} );
		
		stepThread.call( calcTimeCall );
	}
	
	public long getGameTime() {
		return time;
	}

	private class CalculationTime implements ICommand {

		private long ct = -1;
		
		@Override
		public void handle( Object... params ) {
			if( ct == -1 ) {
				ct = System.nanoTime();
				return;
			}
			
			long t = System.nanoTime() - ct;
			ct = -1;
			
			client.display.plainDisplay.container.setTitle(
					SRoot.TITLE +
					" (" + (t/1_000_000) + "ms / " + ALoop.getMemory() + "MB) " +
					getGameTime() );
		}
		
	}
	
}
